#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>

// 宏定义
#define MAXNUM 1000

 // 查找亲近同学
int find_closest_classmate(int *, int, const char *, const char *);
void output(int *, int); // 输出结果

// 测试/驱动
int main()
{
    // 声明变量
    int mno;
    char like[27]; // 26个大写字符+'\0'
    char classmate[MAXNUM + 1];  // MAXNUM个同学+'\0'
    int sno[MAXNUM];

    mno = 1;
    strcpy(like, "ABC");
    strcpy(classmate, "BPTYHJKAMNBPHC");

    // 处理数据
    int n = find_closest_classmate(sno, mno, like, classmate);

    // 输出结果
    output(sno, n);

    return 0;
}

// 查找亲近同学
int find_closest_classmate(int *sno, int myno,
                           const char *like,
                           const char *classmate)
{
    int n = 0;

    // 声明struct re_pattern_buffer对象
    struct re_pattern_buffer pat_buf;
    const char *err_code;
    int match_ret;
    const char *p_str = NULL;

    // 构造正则表达式
    char *pat = (char*)malloc((strlen(like) + 2 + 1) * sizeof(char));
    if(pat == NULL)
    {
        printf("not enough memory!\n");
        exit(EXIT_FAILURE);
    }

    memset(pat, 0, (strlen(like) + 2 + 1) * sizeof(char));

    pat[0] = '[';
    strcat(pat, like);
    strcat(pat, "]");

    // 初始化
    memset(&pat_buf, 0, sizeof(struct re_pattern_buffer));
    re_set_syntax(RE_SYNTAX_EGREP);

    // 编译正则表达式
    err_code  = re_compile_pattern(pat, strlen(pat), &pat_buf);
    if(err_code != NULL)
    {
        printf("error on compiling regex.code = %s\n", err_code);
        exit(EXIT_FAILURE);
    }

    // 从头开始查找
    p_str = classmate;
    // 用正则查找结果作为偏移量
    match_ret = 0;
    do
    {
        // 偏移，为下次查找作准备
        p_str = p_str + match_ret;

        // 用编译后的正则表达式实现查找
        match_ret = re_search(&pat_buf, p_str, strlen(p_str),
                              0, strlen(p_str), NULL);

        // 未找到，退出
        if(match_ret < 0)
        {
            break;
        }

        // 不是自己的学号，记录结果
        if((p_str + match_ret - classmate + 1) != myno)
        {
            sno[n] = p_str + match_ret - classmate + 1;
            n++;
        }

        // 偏移到下一个字符
        match_ret++;
    }while(1);

    // 释放空间
    regfree(&pat_buf);
    free(pat);

    return n; // 返回找到的亲近同学总数
}

// 输出结果
void output(int *sno, int n)
{
    int i;

    if(n > 0)
    {
        for(i = 0; i < n - 1; i++)
        {
            printf("%d ", sno[i]);
        }
        printf("%d\n", sno[i]); // 避免最后输出多1个空格
    }
    else
    {
        printf("Lonely Xiao Ming\n");
    }
}
